package org.luxor.commons.lock4j.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.luxor.commons.core.exception.GlobalLockException;
import org.luxor.commons.lock4j.LockTemplate;
import org.luxor.commons.lock4j.annotation.Lock4j;
import org.luxor.commons.lock4j.core.LockInfo;
import org.luxor.commons.lock4j.core.LockKeyGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 分布式锁aop切面
 *
 * @author zengzh
 * @since 1.0.0
 */
public class LockInterceptor implements MethodInterceptor {
    private static final Logger log = LoggerFactory.getLogger(LockInterceptor.class);
    private final LockKeyGenerator lockKeyGenerator = new LockKeyGenerator();

    private LockTemplate lockTemplate;

    public void setLockTemplate(LockTemplate lockTemplate) {
        this.lockTemplate = lockTemplate;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        LockInfo lockInfo = null;
        try {
            Lock4j lock4j = invocation.getMethod().getAnnotation(Lock4j.class);
            String keyName = lockKeyGenerator.getKeyName(invocation, lock4j);
            lockInfo = lockTemplate.lock(keyName, lock4j.expire(), lock4j.timeout());
            if (null != lockInfo) {
                log.trace(">>> Lock4j 分布式上锁 {}", lockInfo);
                return invocation.proceed();
            }
            throw new GlobalLockException(lock4j.errorCode(), lock4j.errorMsg());
        } finally {
            if (null != lockInfo) {
                if (lockTemplate.releaseLock(lockInfo)) {
                    log.trace("<<< Lock4j 分布式解锁 {}", lockInfo);
                }
            }
        }
    }

}
